package com.gitee.zhziyun.cnfsystem.utils;

import net.jpountz.xxhash.XXHashFactory;
import java.io.*;
import java.nio.file.Files;

/**
 * XXHash工具类，提供文件、字节数组和输入流的哈希计算功能
 * 支持多种返回格式：long型、字节数组型和十六进制字符串型
 */
public class XXHashUtil {
    private static final XXHashFactory XXHASH_FACTORY = XXHashFactory.fastestInstance();
    private static final long DEFAULT_SEED = 0L;
    private static final int BUFFER_SIZE = 8192; // 8KB缓冲区

    // ------------------- 哈希计算核心方法 -------------------
    /**
     * 计算文件哈希并返回long形式
     * 
     * @param file 需要计算哈希的文件
     * @return 文件的哈希值（long形式）
     * @throws IOException 如果读取文件时发生IO异常
     */
    public static long calculateFileHashToLong(File file) throws IOException {
        try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
            return calculateStreamHash(bis);
        }
    }
    
    /**
     * 计算文件哈希并返回字节数组形式
     * 
     * @param file 需要计算哈希的文件
     * @return 文件的哈希值（字节数组形式）
     * @throws IOException 如果读取文件时发生IO异常
     */
    public static byte[] calculateFileHash(File file) throws IOException {
        return longToBytes(calculateFileHashToLong(file));
    }
    
    /**
     * 计算文件哈希并返回十六进制字符串形式
     * 
     * @param file 需要计算哈希的文件
     * @return 文件的哈希值（十六进制字符串形式）
     * @throws IOException 如果读取文件时发生IO异常
     */
    public static String calculateFileHashToString(File file) throws IOException {
        return longToHexString(calculateFileHashToLong(file));
    }

    /**
     * 计算字节数组哈希并返回long形式
     * 
     * @param data 需要计算哈希的字节数组
     * @return 字节数组的哈希值（long形式）
     */
    public static long calculateHashToLong(byte[] data) {
        return XXHASH_FACTORY.hash64().hash(data, 0, data.length, DEFAULT_SEED);
    }
    
    /**
     * 计算字节数组哈希并返回字节数组形式
     * 
     * @param data 需要计算哈希的字节数组
     * @return 字节数组的哈希值（字节数组形式）
     */
    public static byte[] calculateHash(byte[] data) {
        return longToBytes(calculateHashToLong(data));
    }
    
    /**
     * 计算字节数组哈希并返回十六进制字符串形式
     * 
     * @param data 需要计算哈希的字节数组
     * @return 字节数组的哈希值（十六进制字符串形式）
     */
    public static String calculateHashToString(byte[] data) {
        return longToHexString(calculateHashToLong(data));
    }

    /**
     * 计算输入流哈希并返回long形式
     * 
     * @param inputStream 需要计算哈希的输入流
     * @return 输入流数据的哈希值（long形式）
     * @throws IOException 如果读取输入流时发生IO异常
     */
    private static long calculateStreamHash(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[BUFFER_SIZE];
        long hash = DEFAULT_SEED;
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            hash = XXHASH_FACTORY.hash64().hash(buffer, 0, len, hash);
        }
        return hash;
    }

    // ------------------- 字节数组与long互转 -------------------
    /**
     * 将long类型的哈希值转换为字节数组
     * 
     * @param value long类型的哈希值
     * @return 字节数组形式的哈希值
     */
    private static byte[] longToBytes(long value) {
        return new byte[] {
                (byte)(value >> 56), (byte)(value >> 48),
                (byte)(value >> 40), (byte)(value >> 32),
                (byte)(value >> 24), (byte)(value >> 16),
                (byte)(value >> 8),  (byte)value
        };
    }
    
    /**
     * 将long类型的哈希值转换为十六进制字符串
     * 
     * @param value long类型的哈希值
     * @return 十六进制字符串形式的哈希值
     */
    private static String longToHexString(long value) {
        return Long.toHexString(value);
    }
}